;(function () {
    var Colorizr = L.TileLayer.extend({
        // 和普通TileLayer一样，接收两个参数，地图服务地址，和一个配置项
        initialize: function (url, options) {
            // 同 Object.assign({}, L.TileLayer.prototype.options, options, {colorize: ()=>{}, crossOrign:true})
            options = L.extend(
                {},
                L.TileLayer.prototype.options,
                {
                    colorize: function (pixel) {
                        return pixel
                    },
                    crossOrigin: true
                },
                options
            )
            // 调用TileLayer的initalize方法，JS常用继承方式
            L.TileLayer.prototype.initialize.call(this, url, options)

            // not clear, probably equals to "this.options = options"
            L.setOptions(this, options)

            // call setColorizr
            this.setColorizr(this.options.colorize)

            // bind event. when tile loaded, call colorize to custom tile
            this.on('tileload', function (e) {
                this._colorize(e.tile)
            })
        },

        setColorizr: function (colorizrFactory) {
            if (!colorizrFactory || typeof colorizrFactory !== 'function') {
                throw (
                    'The colorize option should be a function and return an object with at least one of "r", "g", "b", or "a" properties. Got:' +
                    typeof colorizrFactory
                )
            } else {
                this.options.colorize = colorizrFactory
            }

            this.redraw(true)
        },

        // perhaps called by L
        _createTile: function () {
            var tile = L.TileLayer.prototype._createTile.call(this)
            tile.crossOrigin = 'Anonymous'
            return tile
        },

        _colorize: function (img) {
            // cached by key <data-colorized>
            if (img.getAttribute('data-colorized')) return
            img.crossOrigin = ''
            var canvas = document.createElement('canvas')
            canvas.width = img.width
            canvas.height = img.height
            var ctx = canvas.getContext('2d')
            ctx.drawImage(img, 0, 0)

            // get pixel data by getImageData();
            var imgd = ctx.getImageData(0, 0, canvas.width, canvas.height)
            var pix = imgd.data

            for (var i = 0, n = pix.length; i < n; i += 4) {
                var pixel = this.options.colorize({
                    r: pix[i],
                    g: pix[i + 1],
                    b: pix[i + 2],
                    a: pix[i + 3]
                })
                if (
                    !!!pixel ||
                    pixel !== Object(pixel) ||
                    Object.prototype.toString.call(pixel) === '[object Array]'
                ) {
                    if (i === 0) {
                        throw 'The colorize option should return an object with at least one of "r", "g", "b", or "a" properties.'
                    }
                } else {
                    if (pixel.hasOwnProperty('r') && typeof pixel.r === 'number') {
                        pix[i] = pixel.r
                    }
                    if (pixel.hasOwnProperty('g')) {
                        pix[i + 1] = pixel.g
                    }
                    if (pixel.hasOwnProperty('b')) {
                        pix[i + 2] = pixel.b
                    }
                    if (pixel.hasOwnProperty('a')) {
                        pix[i + 3] = pixel.a
                    }
                }
            }
            // update to image
            ctx.putImageData(imgd, 0, 0)
            // cahce key
            img.setAttribute('data-colorized', true)
            img.src = canvas.toDataURL()
        }
    })

    // standard registry
    ;(function (factory, window) {
        // define an AMD module that relies on 'leaflet'
        if (typeof define === 'function' && define.amd) {
            define(['leaflet'], factory)

            // define a Common JS module that relies on 'leaflet'
        } else if (typeof exports === 'object') {
            module.exports = factory(require('leaflet'))
        }

        // attach your plugin to the global 'L' variable
        if (typeof window !== 'undefined' && window.L) {
            window.L.tileLayer.colorizr = factory(L)
        }
    })(function (L) {
        return function (url, options) {
            return new Colorizr(url, options)
        }
    }, window)
})()
